package com.gdepri.cabelwellserver.handler;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.gdepri.cabelwellserver.entity.CabelMessage;
import com.gdepri.cabelwellserver.tools.ByteFun;
import com.gdepri.cabelwellserver.tools.Cp56Time2aUtil;
import com.mysql.cj.util.StringUtils;
import org.apache.poi.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;

public class BusinessHandler {

    private final int M_05 = 1; //状态码05，变化数据的M是1，表示1个字节
    private final int N_05 = 2; //状态码05，变化数据的N是4，表示4个字节

    private final int M_06 = 1; //状态码06，全数据的M是1，表示1个字节
    private final int N_06 = 2; //状态码06，全数据的N是4，表示4个字节
    private final int K_06 = 4; //状态码06，全数据的K是4，表示4个字节





    private Logger logger = LoggerFactory.getLogger(BusinessHandler.class);
    public void BusinessRouter(CabelMessage message){
        logger.info("----------------BusinessRouter----------------");
        if(message!=null){
            int funcCode = message.getFuncCode();
            logger.info("当前的功能码为："+funcCode);
            switch (funcCode){
                case 0: confirm(message);break;
                case 1: timesync();break;
                case 2: total();break;
                //case 3: control();break;
                case 4: SOE(message);break;
                case 5: changeData(message);break;
                case 6: allData(message);break;
                case 7: historyData(message);break;
                case 8: parameterSet(message);break;
                //case 16: ipInfo();break;
                default:
                    logger.info("未知功能码:"+funcCode);
            }
        }else {
            logger.info("当前的报文对象为空！");
        }
    }


    public void confirm(CabelMessage message){
        logger.info("00 确认");
    }

    /**
     * 后台到终端，发送时钟同步，终端以00确认，数据Time56A
     * 构造一个报文
     * @return CabelMessage
     */
    public CabelMessage timesync(){
        logger.info("01 时钟同步");
        CabelMessage message = new CabelMessage();
        message.setFuncCode(1);//01时钟同步
        message.setDirection("1");//表示来自服务器
        message.setAddress(65535);//地址是ff广播地址
        byte[] currentCP56TimeByteArr = Cp56Time2aUtil.getCurrentCP56TimeByteArr();
        message.setData(currentCP56TimeByteArr);
        message.setDataLength(currentCP56TimeByteArr.length);
        message.setLength(message.getDataLength()+3);
        return message;
    }

    /**
     * 总召其实和对时报文是一样的，只不过数据是空的
     * @return CabelMessage
     */
    public CabelMessage total(){
        logger.info("02 总召");
        CabelMessage message = new CabelMessage();
        message.setFuncCode(2);//02总召
        message.setDirection("1");//表示来自服务器
        message.setAddress(65535);//地址是ff广播地址
        message.setDataLength(0);
        message.setLength(3);
        return message;
    }


    public CabelMessage control(String type1Byte,String address2Byte,String value2Byte){
        logger.info("03 控制，根据类型，地址，值来构成一个数组");
        byte[] controlByteArr = new byte[5];
        int address = 000000000000;
        //to-do

        CabelMessage message = new CabelMessage();
        message.setFuncCode(3);//02总召
        message.setDirection("1");//表示来服务器
        message.setAddress(address);//地址是ff广播地址
        message.setDataLength(5);
        message.setLength(8);
        return message;
    }


    /**
     * 方向是终端到后台，上报SOE记录
     * 数据是 N（1个字节）,N*[地址2字节，状态1字节,时标7字节]
     *
     */
    public void SOE(CabelMessage message){
        logger.info("04 SOE");
        byte[] data = message.getData();
        logger.info("数据大小为："+data.length);
        logger.info(Arrays.toString(data));

        //对数据进行解析
        byte byteN = data[0];
        int N = Byte.toUnsignedInt((byte) byteN);
        logger.info("N:"+N);

        JSONArray arr = new JSONArray();

        int counter =1;
        if(N!=0){
            //从第二个Byte开始,循环，每次遍历10个字节
            for (int i = 0; i < N; i++) {
                int address = ByteFun.getAddress(data[counter], data[counter + 1]);//第3,4个byte共同组成M的地址
                int status = data[counter+2];
                //把data[counter+3]到data[counter+9]单独组成一个数组
                byte[] timeByteArr = new byte[7];
                for (int j = 0; j < 7; j++) {
                    timeByteArr[j] = data[counter+j+3];
                }
                Date date = Cp56Time2aUtil.toDate(timeByteArr);
                logger.info("address:"+address+" status:"+status+" time:"+date);
                JSONObject obj = new JSONObject();
                String key = "DI"+address;
                obj.put(key,status);
                obj.put("event_time",data);
                arr.add(obj);
                arr.add(new JSONObject().fluentPut("address",address).fluentPut("status",status).fluentPut("time",date));
                counter += 10;
            }
        }
        logger.info("SOE数组:"+arr.toJSONString());
        MQTTHandler handler = new MQTTHandler();
        JSONObject obj = new JSONObject();
        obj.put("arr",arr);
        handler.sendData(obj,message.getAddress());
    }


    /**
     *  方向是终端到后台，COS或者遥测变化
     * @param message
     */
    public void changeData(CabelMessage message){
        logger.info("05 变化数据");
        byte[] data = message.getData();
        logger.info("数据大小为："+data.length);
        logger.info(Arrays.toString(data));

        //对数据进行解析
        byte byteM = data[0];
        byte byteN = data[1];

        int M = Byte.toUnsignedInt((byte) byteM);
        int N = Byte.toUnsignedInt((byte) byteN);
        logger.info("M:"+M+" N:"+N);

        JSONObject obj = new JSONObject();

        int counter =2;
        System.out.println("COS数——————————————————————————————————————");
        if(M!=0){
            for (int i = 0; i < M; i++) {
                int address = ByteFun.getAddress(data[counter], data[counter + 1]);//第3,4个byte共同组成M的地址
                int status = Byte.toUnsignedInt(data[counter+2]);
                counter += 3;
                String key = "DI"+address;
                obj.put(key,status);
                logger.info("地址："+address+" 状态："+status);
            }
        }
        System.out.println("AI变化数————————————————————————————————————");
        if(N!=0){
            for (int i = 0; i < N; i++) {
                int address = ByteFun.getAddress(data[counter], data[counter + 1]);//第3,4个byte共同组成M的地址
                //float value = ByteFun.getFloatBy4Bytes(data[counter+2],data[counter+3],data[counter+4],data[counter+5]);
                int value = ByteFun.getDataFromArrByIndex(data,counter+2,counter+6);

                counter += 6;
                String key = "AI"+address;
                obj.put(key,value);
                logger.info("地址："+address+" 状态："+value);
            }
        }
        MQTTHandler handler = new MQTTHandler();
        handler.sendData(obj,message.getAddress());
    }


    /**
     *  方向是终端到后台，  DI/AI/CNT数据合并发送
     * @param message
     */
    public void allData(CabelMessage message){
        logger.info("06 全数据");
        byte[] data = message.getData();
        logger.info("数据大小为："+data.length);
        logger.info(Arrays.toString(data));

        //对数据进行解析
        byte byteM = data[0];
        byte byteN = data[1];
        byte byteK = data[2];

        int M = Byte.toUnsignedInt((byte) byteM);
        int N = Byte.toUnsignedInt((byte) byteN);
        int K = Byte.toUnsignedInt((byte) byteK);
        logger.info("M:"+M+" N:"+N+" K:"+K);

        JSONObject resultObj = new JSONObject();

        int counter =3;
        if(M!=0){
            int addressM = ByteFun.getAddress(data[counter], data[counter + 1]);//第3,4个byte共同组成M的地址
            counter +=2;
            int counterIndex = counter;
            //解析M个DI数据
            counter +=M*M_06;
            logger.info("M的起始地址是:"+addressM);

            for (int i = 0; i < M; i++) {
                //起始的下表是counterIndex,从这个开始才有数据,每次跳跃M*M_06个字节
                int begin = counterIndex+i*M_06;
                int end = begin+M_06;
                int value = ByteFun.getDataFromArrByIndex(data, begin, end);
                String key = "DI"+i;
                resultObj.put(key,value);
                System.out.println("当前的地址："+addressM+++"  数据："+value);
            }

        }
        if(N!=0){
            int addressN = ByteFun.getAddress(data[counter], data[counter + 1]);
            counter +=2;
            int counterIndex = counter;
            //解析N个AI数据
            counter +=N*N_06;
            logger.info("N的起始地址是："+addressN);
            for (int i = 0; i < N; i++) {
                //起始的下表是counterIndex,从这个开始才有数据,每次跳跃N*N_06个字节
                int begin = counterIndex+i*N_06;
                int end = begin+N_06;
                int value = ByteFun.getDataFromArrByIndex(data, begin, end);
                String key = "AI"+i;
                resultObj.put(key,value);
                System.out.println("当前的地址："+addressN+++"  数据："+value);
            }
        }
        if (K!=0){
            int addressK = ByteFun.getAddress(data[counter], data[counter + 1]);
            counter +=2;
            int counterIndex = counter;
            //解析K个CNT数据
            counter +=K*K_06;
            logger.info("K的起始地址是："+addressK);
            for (int i = 0; i < K; i++) {
                //起始的下表是counterIndex,从这个开始才有数据,每次跳跃K*K_06个字节
                int begin = counterIndex+i*K_06;
                int end = begin+K_06;
                int value = ByteFun.getDataFromArrByIndex(data, begin, end);
                String key = "CNT"+i;
                resultObj.put(key,value);
                System.out.println("当前的地址："+addressK+++"  数据："+value);
            }
        }
        MQTTHandler handler = new MQTTHandler();
        handler.sendData(resultObj,message.getAddress());
    }

    //07 历史数据
    public void historyData(CabelMessage message){
        logger.info("07 历史数据");
        byte[] data = message.getData();
        logger.info("数据大小为："+data.length);
        logger.info(Arrays.toString(data));

        //对数据进行解析
        byte byteK = data[0];
        byte byteM = data[1];
        byte byteN = data[2];

        int K = Byte.toUnsignedInt((byte) byteK);
        int M = Byte.toUnsignedInt((byte) byteM);
        int N = Byte.toUnsignedInt((byte) byteN);

        logger.info("K:"+K+" M:"+M+" N:"+N);

        int addressDI_M = ByteFun.getAddress(data[3], data[4]);
        int addressAI_N = ByteFun.getAddress(data[5], data[6]);

        JSONObject result = new JSONObject();
        JSONArray arr = new JSONArray();
        int counter = 7;
        int jumpWidth = 7+M*1+N*4;
        //需要从 data[7]开始遍历K次，每次遍历是 7+M*1+N*4
        for (int i=0;i<K;i++){
            JSONObject historyItem =new JSONObject();
            //时间
            byte[] timeByteArr = new byte[7];
            for (int j = 0; j < 7; j++) {
                timeByteArr[j] = data[counter+j];
            }
            Date date = Cp56Time2aUtil.toDate(timeByteArr);
            historyItem.put("event_time",data);
            System.out.println("时间："+date);

            counter += 7;
            //M*[状态1字节]
            for (int diIndex = 0; diIndex < M; diIndex++){
                int diValue = Byte.toUnsignedInt(data[counter+diIndex]);
                String key = "DI"+addressDI_M;
                historyItem.put(key,diValue);
                System.out.println("DI地址："+addressDI_M++ +"状态："+diValue);
            }
            counter += M;
            //N*[值4字节 浮点]
            for (int aiIndex = 0; aiIndex < N; aiIndex++){
                //float aiValue = ByteFun.getFloatBy4Bytes(data[counter+aiIndex],data[counter+aiIndex+1],data[counter+2+aiIndex],data[counter+3+aiIndex]);
                int   aiValue = ByteFun.getDataFromArrByIndex(data,counter+aiIndex,counter+aiIndex+4);
                String key = "AI"+addressAI_N;
                historyItem.put(key,aiValue);
                System.out.println("AI地址："+addressAI_N++ +"状态："+aiValue);
            }
            counter += M*4;
            arr.add(historyItem);
        }
        result.put("arr",arr);
        MQTTHandler handler = new MQTTHandler();
        handler.sendData(result,message.getAddress());
    }


    //08 参数设置
    public void parameterSet(CabelMessage message){
        logger.info("08 参数设置");
    }


    //0f 配置网络参数
    public CabelMessage ipInfo(String ip,int port){
        CabelMessage res = null;
        logger.info("0f 配置网络参数");
        logger.info("ip:"+ip+" port:"+port);
        int ipA = 0;
        int ipB = 0;
        int ipC = 0;
        int ipD = 0;

        //校验端口
        if (port <0 || port > ((long)256*256*256*256)){
            System.out.println("port:"+port+",不符合规范！");
            return res;
        }

        //校验ip
        if (StringUtils.isNullOrEmpty(ip) ){
            System.out.println("ip:"+ip+"为空,不符合规范！");
            return res;
        }else {
            String[] split = ip.split("\\.");
            if (split.length != 4){
                System.out.println(Arrays.toString(split));
                System.out.println(split.length);
                System.out.println("ip:"+ip+",长度不符合规范！");
                return res;
            }else{
                for (int i = 0; i < split.length; i++) {
                    if (Integer.parseInt(split[i]) < 0 || Integer.parseInt(split[i]) > 255){
                        System.out.println("ip:"+ip+",不符合规范！");
                        return res;
                    }else {
                        switch (i){
                            case 0:
                                ipA = Integer.parseInt(split[i]);
                                break;
                            case 1:
                                ipB = Integer.parseInt(split[i]);
                                break;
                            case 2:
                                ipC = Integer.parseInt(split[i]);
                                break;
                            case 3:
                                ipD = Integer.parseInt(split[i]);
                                break;
                        }
                    }
                }
            }
        }

        //port转换成4字节的byte
        byte[] portByteArr = ByteFun.intTo4Bytes(port);

        //ipA转换成1个字节的byte
        byte[] ipByteArr = new byte[4];
        ipByteArr[0] = (byte) ipA;
        ipByteArr[1] = (byte) ipB;
        ipByteArr[2] = (byte) ipC;
        ipByteArr[3] = (byte) ipD;

        byte[] data = new byte[8];
        //把ipByteArr和portByteArr赋值到data数组中
        for (int i = 0; i < 4; i++) {
            data[i] = ipByteArr[i];
        }
        for (int i = 4; i < 8; i++) {
            data[i] = portByteArr[i-4];
        }

        res = new CabelMessage();
        res.setData(data);
        res.setFuncCode(15);//0x0f
        res.setDirection("1");//表示来自服务器
        res.setAddress(65535);//地址是ff广播地址
        res.setDataLength(data.length);
        res.setLength(data.length+3);

        return res;
    }


}
